#!/bin/bash

#----------------------------MGS Burner------------------------------
#A Bash GTK3 interface for optical image burning.
#--------------------------------------------------------------------
#
#Copyright (C) 2013  Matías Gastón Santiago.
#Contact: <matiasbatero.mdq@gmail.com>

#This program is free software: you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation, either version 3 of the License, or
#(at your option) any later version.

#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.

#You should have received a copy of the GNU General Public License
#along with this program.  If not, see <http://www.gnu.org/licenses/>

#--------------------------------------------------------------------

#Dependencies: cdrdao, dvd+rw-tools, pv, zenity
#This script run entirely in BASH. 


#VERSION 1.02 23/12/2013

#Added pv as dependency
#Added USB Flash disk support

#----------------------------------------------------------------------

#VERSION 1.01 22/12/2013

#Added dependency checks
#--------------------------------------------------------------------

#VERSION 1.0 22/12/2013

#Added support for ISO 9660 / UDF images.
#Only DVD/BD and (+RW) are supported. CD/CDRW will be supported on next releases.
#Zenity GTK 3 is used for graphical user interface dialogs.

#NOTE: Current software was tested using DVD+R, DVD-R, DVD+RW.
#Blu-Ray works similar but needs feedback. I don't have BD Burning drive, and (it's expensive).
#Warning: Double Layer based disk are not tested, (it's expensive). Some drives needs a jump layer data.
#This case is not contempled.

#-------------------------------------------------------------------

dialog(){

case $1 in

'--mainlist')
devices(){
(cdrdao scanbus 2>&1 | sed 1d | sed 's/ //g' | sed 's/\:/ \: /g' | sed 's/\,/ /g') | while read line ;do echo "$line" ;done

find /dev/sd*  | while read line; do

vendor=`udevadm info --query=property --name=$line | grep -E 'ID_VENDOR' | sed 3d | sed 2d | sed 's/ID_VENDOR=//g'`
id=`udevadm info --query=property --name="$line" | grep ID_BUS | sed 's/ID_BUS=//g'`
capacity=`lsblk "$line" | grep disk | awk '{ print $4}'`
model=`udevadm info --query=property --name=$line | grep -E 'ID_MODEL' | sed 3d | sed 2d | sed 's/ID_MODEL=//g' | sed 's/_/ /g'`
sys=`lsblk $line | grep disk | awk '{print $6}'`

if [ "$sys" = 'disk' ];then
    if [ "$id" = 'usb' ];
        then
        echo "$line : USB $capacity $vendor $model"
    fi
fi


done;
}

devices | zenity --list --width=500 --height=300 --window-icon=question --title="Select drive" --text="<b>($( devices | grep -c dev)) device/s found.</b>\nIf your device was not detected, verify it manually.\n " --ok-label="Next" --column="Path" 2> /dev/null
;;

'--manual')
zenity --entry --title="Custom device" --text='Specify device full path:' --entry-text='/dev/example'
;;

'--empty')
zenity --error --title="Error" --text="Device $2 is empty.\nInsert a blank disk or RW medium and try again."
;;

'--used')
zenity --error --title="Error" --text="Current medium is already written.\nInsert a blank disk or RW medium and try again."
;;


'--invalid')
zenity --error --title="Error" --text="Unable to connect with $2 path device.\nVerify that device path is correct and try again."
;;

'--invalid_file')
zenity --error --title="Error" --text="Invalid image file. Please try again."
;;

'--nullpath')
zenity --error --title="Error" --no-wrap --text="Null device paths are not allowed. Try again."
;;

'--abort')
return 1
;;

'--aborted')
zenity --error --title="Error" --no-wrap --text="Aborted by user. Retry again later."
;;

'--rw')
zenity --question --title="RW medium found" --no-wrap --text="Rewritable medium found, but it\'s already written and needs format to continue.\nDo you wan\'t to continue?\n\n<i>All data from current disk will be lost, and format will perfomed in fast mode.</i>"
;;

'--speed_dvd')
min=$(( $(cat /tmp/log | grep -c "Descriptor#")-1))

(cat /tmp/log | grep "Write Speed" | sed 1d | sed 's/x1385=/X /g' | sed 's/Write Speed \#//g' | sed 's/\://g') | while read LINE ;do

id=$(echo $LINE | awk '{print $1}')
speed=$(echo $LINE | awk '{print $2}')
rate=$(echo $LINE | awk '{print $3}')

if [ $id = $min ]; 
    then
        echo "TRUE";echo "$speed"; echo "$rate"
    else
        echo "FALSE";echo "$speed"; echo "$rate"
fi


done | zenity --list --radiolist --width=500 --height=300 --column=' ' --column="Speed" --title="Select write speed" --text="Current write speeds for medium at : $dev.\nNOTE: Choose a low speed if you want minimize failure risks." --column="Rate (KB/s)" 2> /dev/null
;;


'--speed_cd')
max=`cdrdao drive-info --device $dev | grep 'Maximum writing' | rev | cut -d\  -f 2 | rev`
limit=$(printf %0.f `echo $max/150 | bc -l`)
    
case $type in

cdrw)
    
    (
    
    for i in `seq $limit -2 2`; do
    
    echo "FALSE"; echo "$i"X; echo $(($i*150))
    
    done 
    
    echo "TRUE"; echo "1X"; echo "150" 
    
    )| zenity --list --radiolist --width=500 --height=300 --column=' ' --column="Speed" --title="Select write speed" --text="Current write speeds for medium at : $dev.\nNOTE: Choose a low speed if you want minimize failure risks." --column="Rate (KB/s)" 2> /dev/null
;;

cd)

    (
    
    for i in `seq $limit -8 8`; do
    
    echo "FALSE"; echo "$i"X; echo $(($i*150))
    
    done 
    
    echo "TRUE"; echo "1X"; echo "150" 
    
    )| zenity --list --radiolist --width=500 --height=300  --column=' ' --column="Speed" --title="Select write speed" --text="Current write speeds for medium at : $dev.\nNOTE: Choose a low speed if you want minimize failure risks." --column="Rate (KB/s)" 2> /dev/null
;;



esac
;;

'--root')
zenity --password --title="Administrative access"
;;

'--root_err')
zenity --error --no-wrap --title='Error' --text="Administrative password is invalid. Contact your system administrator and retry again."
;;

'--mount_err2')
zenity --question --title="Already mounted" --no-wrap --text="$2 is mounted at following mountpoints:\n\n$(lsblk $2 -o NAME,MOUNTPOINT)\n\nUnmonted device is required to perform this operation.\nDo you want to unmount devices and continue?\n\n<i>NOTE: This operation require privileges</i>"
;;

'--mount_err')
zenity --error --title="Already mounted" --no-wrap --text="$2 is mounted at following mountpoints:\n\n$(lsblk $2 -o NAME,MOUNTPOINT)\n\nUnmonted device is required to perform this operation.\nYou can do it manually using \n\n<i>sudo umount \"mountpoint\"</i>\n\nPlease unmount these devices and try again."
;;

'--notyet')
zenity --error --no-wrap --title='Not supported' --text="At this moment CD is not supported yet. Only DVD/BD.\nThis feature will be available on next releases\n\nInsert a blank DVD/BD and try it again." 

;;

'--burn_confirmation')
text="Confirm the operation to start the writing process:\n\nDevice: $dev \nImage path: $file \nWriting speed: $speed\n\nClick yes to begin.\n\n<i>NOTE: Process cannot be stopped until be finished. Be sure before continue.</i>"
zenity --question --no-wrap --title='Confirmation' --text="$text"
;;

'--usb_confirmation')
zenity --question --no-wrap --title='Confirmation' --text="This operation will destroy all current data on $2.\nThis action is irreversible, do you want to continue?\n\nNOTE: This process due dd, works entirely on background. Don\'t extract your USB Flash device, you will be notified when it\'s done 100%."
;;

'--compatibility') 
zenity --question --no-wrap --title="Compatibility" --text="Only open standard formats ISO/UDF are allowed to be burned directly over media without any loss of data.\n\nPropietary or non-standard formats, needs a conversion step to ISO standard format to be recognized.\n\nAny conversion from non-standard formats are not exactly, because data structures are only know by format owners.\nIn most cases, ~5% sizes differences after conversion are not relationated with damaged/loss data and information is safe.\nBut, sometimes differences are considerable and data could be corrupt/lost like images built from multisector disks.\n\nConversion will be perfomed, then you can evaluate if integrity is acceptable and proceed burning.\nDo you want to continue?"
;;

'--file')
zenity --file-selection --title="Select image" --text="available" --filename=$HOME/ \
--file-filter="All supported images | *.iso *.ISO *.udf *.UDF" \
--file-filter="Standard ISO (*.iso)| *.iso *.ISO" \
--file-filter="Standard UDF (*.udf) | *.udf *.UDF" \
;;

'--finished_usb')
zenity --info --no-wrap --title="Finished" --text="Process complete. It\'s recommended to not eject your pendrive/memory from your computer for 5/10 min.\nIn most common systems, asynchronous copy could be active still after process.\n\n<i>NOTE: Don\'t extract your pendrive by force, use eject option instead.</i>"
;;

'--missing')
    zenity --error --no-wrap --title="Error" --text="Required packages are missing on your system:\n\n$2\n\nPlease install these packages and try again."
;;

esac

}

check(){
case $1 in    

--dvdrw)
cat /tmp/log | grep "Mounted" | grep -c RW
;;

--dvdblank)
cat /tmp/log | grep "Disc status" | cut -d: -f2 | sed 's/ //g'
;;

--packages)

rm '/tmp/unmet'

if [ `which zenity` ]; 
    then
        for i in cdrdao growisofs pv; do
        
        if [ `which "$i"` ]; then
            if [ "$i" = 'growisofs' ];then echo "dvd+rw-tools : Found" >> /tmp/unmet ;else    echo "$i" : Found >> /tmp/unmet;fi
            
            else
            
            if [ "$i" = 'growisofs' ];then echo "dvd+rw-tools : Found"  >> /tmp/unmet ;err=2 ;else    echo "$i" : Not found >> /tmp/unmet;err=2;fi
        fi
        
        done
        
        if [ "$err" = 2 ];
        then
            
            dialog --missing "$(cat /tmp/unmet)"
            exit 2
        fi
    else
        xterm -e "echo Zenity is not installed on this system, please install it and try again.;read"
        exit 2
fi
;;

esac
}

ask_device(){
dev=`dialog --mainlist` || return 1 

if [ -z "$dev" ]; then zenity --error --title="Error" --text="No device selected, please select one before continue";i=2;return 1; else

dev=`echo $dev | awk '{print $1}'`

(dvd+rw-mediainfo $dev > /tmp/log) 2> /dev/null

case $? in

    0)  
        if [ `cat /tmp/log | grep "Disc status" | cut -d: -f2 | sed 's/ //g'` = 'blank' ]
            then
                type='dvd'
            
            else 
                if [ `cat /tmp/log | grep "Mounted" | grep -c RW` = 1 ]
                    then
                    type='dvdrw'
                    
                    else
                    dialog --used && i=2;return 1
                fi
        fi
            
    ;;
    
    252) 
    
    dialog --notyet && i=2;return 1
    ;;
    
    251) 
    dialog --empty "$dev" && i=2;return 1
    ;;
    
    150)
    type='usb'    
    disconnect=`lsblk $dev -o MOUNTPOINT | grep "/"`
    if [ -z "$disconnect" ]
    then
        echo "$dev is ready"
    else
        echo "$dev is not ready. You need umount device before use it"
        dialog --mount_err "$dev" && i=2;return 1
        
        
    fi
    ;;
    
            
esac

fi

}

ask_file(){
file=`dialog --file` || return 1

if [ -f "$file" -a -r "$file" -a -s "$file" ] 
    then
    
        case `echo $file | rev | cut -d. -f 1 | rev | sed 's/\(.*\)/\L\1/'` in
                            
            iso|udf)
            return 0
            ;;
            
            
            *) 
            dialog --invalid_file && return 1
            ;;
        
        esac 
    else
    
    dialog --invalid_file && return 1
fi


}

ask_speed(){

case $type in

dvd|dvdrw)
speed=`dialog --speed_dvd` || return 1
;;

cd|cdrw)
speed=`dialog --speed_cd` || return 1
;;

usb)
return 0
;;

esac
speed=$(echo $speed | sed 's/X//g')

}

burn(){

case $type in

dvd)
(( growisofs -dvd-compat -use-the-force-luke -Z "$dev"="$file" -speed="$speed"  ) | while read line ;do echo $line | awk '{print $2}' | sed 's/(//g' | sed 's/)//g' ;done) | zenity --progress --width=500 --height=200 --no-cancel --auto-close --percentage=0 --text="Burning, please wait..." --title="Burning image"

;;

dvdrw)
dvd+rw-format "$dev" | awk '{ print $1; fflush() }' | zenity --progress --width=500 --height=200 --no-cancel --auto-close --percentage=0 --text="Formating, please wait..." --title="Preparing RW medium"

(( growisofs -dvd-compat -use-the-force-luke -Z "$dev"="$file" -speed="$speed"  ) | while read line ;do echo $line | awk '{print $2}' | sed 's/(//g' | sed 's/)//g' ;done) | zenity --progress --width=500 --height=200 --no-cancel --auto-close --percentage=0 --text="Burning, please wait..." --title="Burning image"

;;

usb)
notify(){
notify-send "Working at background..." "When process its done 100% you will notified\nDon't extract your USB during process."
}

dialog --usb_confirmation $dev && cont='yes' #|| ( i=3;return 1 )

if [ "$cont" = "yes" ]
    then
        notify
        echo "working"
        (pv -n "$file" | dd of="$dev" bs=4M ) 2>&1 | zenity --progress --width=500 --height=200 --no-cancel --auto-close --percentage=0 --title="Writing USB" --text="Copying, please wait.. \nDon\'t extract your USB during process, you can damage it"
        dialog --finished_usb
        return 0
    else
        i=3
        return 1
fi

#dd bs=4M if="$file" of="$dev" && sync | zenity --progress --no-cancel --auto-close --pulsate
#(pv -n "$file" | dd of="$dev" bs=4M ) 2>&1 | zenity --progress --width=500 --height=200 --no-cancel --auto-close --percentage=0 --title="Writing USB" --text="Copying, please wait.. \nDon\'t extract your USB during process, you can damage it"

;;

esac

}




main(){

echo "Process step $i"

case $1 in 

1) ask_device && let i++ || let i--
;; 

2) ask_file && let i++ || let i--
;;

3) ask_speed && let i++ || let i--
;;

4) burn && exit 0 || let i--
;;

0) exit 1 #aborted

;;

*) exit 0
;;

esac

main $i


}


check --packages

i=1 
main 1



